package com.youdoneed.friends.friends;

import com.querydsl.core.Tuple;
import com.querydsl.core.types.QBean;
import com.querydsl.sql.SQLQuery;
import com.querydsl.sql.SQLQueryFactory;
import com.querydsl.sql.dml.SQLUpdateClause;
import com.youdoneed.base.application.AppException;
import com.youdoneed.base.common.GlobalIdWorker;
import com.youdoneed.community.feign.ForumClient;
import com.youdoneed.community.forum.entity.Forumnotice;
import com.youdoneed.friends.Const.CoolfaceNoticeType;
import com.youdoneed.friends.application.QueryHelper;
import com.youdoneed.friends.coolface.FaceSearchService;
import com.youdoneed.friends.model.FaceSearch;
import com.youdoneed.friends.model.Friends;
import com.youdoneed.friends.model.FriendsConfirm;
import com.youdoneed.friends.query.QFaceSearch;
import com.youdoneed.friends.query.QFriendsConfirm;
import com.youdoneed.friends.vo.CoolfaceRequestVo;
import com.youdoneed.friends.vo.DataCounts;
import com.youdoneed.friends.vo.FindFriendsConfirmVO;
import com.youdoneed.user.feign.UserFeignClient;
import com.youdoneed.user.model.CoolfaceNotice;
import com.youdoneed.user.model.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional
public class FriendsConfirmService {

    private final Logger logger = LoggerFactory.getLogger(FriendsConfirmService.class);

    //标题
    public static final String TITLE = "Cooface";

    //申请加你为好友
    public static final String APPLYTOBEFRIENDMSG = " 申请加你为好友，快来看看";

    //确认添加你为好友
    public static final String CONFIRMTOBEFRIENDMSG = " 确认添加你为好友，快来看看";

    //有人通过Coolface加你为好友
    public static final String APPLYTOBEFRIENDBYCOOLFACEMSG = " 有人通过Coolface加你为好友，快来看看";

    //Coolface过的人，加你为好友
    public static final String COOLFACECONFIRMTOBEFRIENDMSG = " 你之前Coolface的人，添加你为好友了";

    //你Coolface的TA，最近注册了
    public static final String COOLFACEDUSERREGISTERMSG = " 你之前Coolface的人，刚刚注册了";

    //我coolface过的注册了
    public static final String COOLFACEDUSERREGISTER = "coolfacedUserRegister";

    //别人添加我为好友
    public static final String APPLYTOBEFRIEND = "applyToBeFriend";

    //被他人同意加为好友
    public static final String CONFIRMTOBEFRIEND = "confirmToBeFriend";

    //Coolface过的人，加你为好友
    public static final String COOLFACECONFIRMTOBEFRIEND = " coofaceConfirmToBeFriend";

    //Coolface找你的
    public static final String APPLYTOBEFRIENDBYCOOLFACE = " applyToBeFriendByCoolface";

    @Autowired
    private SQLQueryFactory queryFactory;
    private QFriendsConfirm qFriendsConfirm = QFriendsConfirm.FriendsConfirm;
    private QFaceSearch qFaceSearch = QFaceSearch.FaceSearch;

    @Autowired
    private FriendsService friendsService;

    @Autowired
    private FaceSearchService faceSearchService;

    @Autowired
    private UserFeignClient userFeignClient;

    @Autowired
    private ForumClient forumClient;


    public FriendsConfirm getConfirmById(String confirmId) {
        if (!StringUtils.hasText(confirmId)) {
            throw new AppException("好友请求ID不能为空");
        }
        return queryFactory.selectFrom(qFriendsConfirm)
                .where(qFriendsConfirm.confirmId.eq(confirmId))
                .fetchOne();
    }

    /**
     * 更新或新增好友请求
     */
    public long updateOrInsert(FriendsConfirm confirm) {
        long update = queryFactory.update(qFriendsConfirm)
                .populate(confirm)
                .where(qFriendsConfirm.userId.eq(confirm.getUserId()))
                .where(qFriendsConfirm.friendId.eq(confirm.getFriendId()))
                .execute();
        if (update < 1) {
            confirm.setConfirmId(GlobalIdWorker.nextString());
            confirm.setCreateTime(new Date());
            return queryFactory.insert(qFriendsConfirm)
                    .populate(confirm)
                    .execute();
        } else {
            return update;
        }
    }

    /**
     * 保存coolface加好友请求，请求发送之后，被请求的用户将在coolfacenotice中获取一条coolface加好友的请求
     *
     * @param userId
     * @param friendId
     * @param searchId
     * @author lid
     * @date 2017.11.10
     */
    public void saveCoolfaceConfirm(String userId, String friendId, String searchId) {
        if (!StringUtils.hasText(userId)) {
            throw new AppException("用户ID不能为空");
        }

        if (!StringUtils.hasText(friendId)) {
            throw new AppException("friendId不能为空");
        }

        if (!StringUtils.hasText(searchId)) {
            throw new AppException("searchId不能为空");
        }

        if (userId.equals(friendId)) {
            throw new AppException("您不能添加自己为好友");
        }

        User user = userFeignClient.getUser(userId).getData();
        if (null == user) {
            throw new AppException("未找到当前用户!");
        }

        // 查看已存在的好友
        Friends friendsOld = friendsService.getFriends(userId, friendId);
        if (friendsOld != null) {
            if (friendsOld.getBlBlack().equals(0)) {
                throw new AppException("该用户不允许您添加为好友");
            } else {
                throw new AppException("该用户已经是您的好友了");
            }
        }

        User friendInfo = userFeignClient.getUser(friendId).getData();
        if (friendInfo == null) {
            throw new AppException("该用户已不存在");
        }
        //判断对方是否允许被加好友
        if (!friendInfo.getAllowAddMe().equals(1)) {
            throw new AppException("该用户不允许添加为好友");
        }

        // 存在对方添加我为好友则表示同意加好友
        String confirmId = queryFactory.select(qFriendsConfirm.confirmId)
                .from(qFriendsConfirm)
                .where(qFriendsConfirm.userId.eq(friendId))
                .where(qFriendsConfirm.friendId.eq(userId))
                .fetchFirst();
        if (StringUtils.hasText(confirmId)) {
            updateConfirm(confirmId, null, 1);
            return;
        }
        // 开始发起加好友
        FriendsConfirm confirm = new FriendsConfirm();
        confirm.setUserId(userId);
        confirm.setFriendId(friendId);
        confirm.setSearchId(searchId);
        confirm.setUserImageUrl(user.getImageUrl());

        // 是否自动确认加好友
        if (friendInfo.getAutoAgreeAddMe().equals(1)) {
            confirm.setHandleFlag(1);
            friendsService.saveFriends(userId, friendId);
        } else {
            confirm.setHandleFlag(0);
        }

        updateOrInsert(confirm);

        //推送消息
        forumClient.pushMessageForExtraMsg(friendInfo.getNoticeRegId(),
                FriendsConfirmService.TITLE, FriendsConfirmService.APPLYTOBEFRIENDBYCOOLFACEMSG,
                FriendsConfirmService.APPLYTOBEFRIENDBYCOOLFACE);
    }

    /**
     * 获取我被coolface加好友的请求
     *
     * @param userId
     * @author lid
     * @date 2017.11.10
     */
    public List<CoolfaceRequestVo> getCoolfaceRequest(String userId) {
        QBean<FriendsConfirm> friendsConfirmBean = QueryHelper
                .matchToBean(FriendsConfirm.class, qFriendsConfirm);
        QBean<FaceSearch> faceSearchBean = QueryHelper
                .matchToBean(FaceSearch.class, qFaceSearch);

        List<Tuple> tuples = queryFactory.select(
                friendsConfirmBean, faceSearchBean)
                .from(qFriendsConfirm)
                .leftJoin(qFaceSearch)
                .on(qFriendsConfirm.searchId.eq(qFaceSearch.searchId))
                .where(qFriendsConfirm.searchId.isNotNull())
                .where(qFriendsConfirm.friendId.eq(userId))
                .where(qFriendsConfirm.handleFlag.eq(0))
                .orderBy(qFriendsConfirm.createTime.desc())
                .fetch();

        List<CoolfaceRequestVo> listCoolfaceRequestVo = new ArrayList<CoolfaceRequestVo>();
        if ((null == tuples)
                || (0 == tuples.size())) {
            logger.info("0 == tuples.size()");

            return listCoolfaceRequestVo;
        }
        for (Tuple tuple : tuples) {
            FriendsConfirm friendsConfirm = tuple.get(friendsConfirmBean);
            FaceSearch faceSearch = tuple.get(faceSearchBean);
            CoolfaceRequestVo vo = new CoolfaceRequestVo();
            vo.setFaceSearch(faceSearch);
            vo.setFriendsConfirm(friendsConfirm);
            listCoolfaceRequestVo.add(vo);
        }

        logger.info("listCoolfaceRequestVo.size():" + listCoolfaceRequestVo.size());
        return listCoolfaceRequestVo;
    }

    /**
     * 保存好友请求
     */
    public void saveConfirm(String userId, String notice, List<String> friendIdList) {
        if (!StringUtils.hasText(userId)) {
            throw new AppException("用户ID不能为空");
        }
        if (friendIdList == null || friendIdList.size() < 1) {
            throw new AppException("好友ID不能为空");
        }

        for (String friendId : friendIdList) {
            if (!StringUtils.hasText(friendId)) {
                continue;
            }
            if (userId.equals(friendId)) {
                throw new AppException("您不能添加自己为好友");
            }

            // 查看已存在的好友
            Friends friendsOld = friendsService.getFriends(userId, friendId);
            if (friendsOld != null) {
                if (friendsOld.getBlBlack().equals(0)) {
                    throw new AppException("您不能添加黑名单的用户为好友");
                } else {
                    throw new AppException("该用户已经是您的好友了");
                }
            }

            User friendInfo = userFeignClient.getUser(friendId).getData();
            if (friendInfo == null) {
                throw new AppException("该用户已不存在");
            }
            //判断对方是否允许被加好友
            if (!friendInfo.getAllowAddMe().equals(1)) {
                throw new AppException("该用户不允许添加为好友");
            }

            // 存在对方添加我为好友则表示同意加好友
            String confirmId = queryFactory.select(qFriendsConfirm.confirmId)
                    .from(qFriendsConfirm)
                    .where(qFriendsConfirm.userId.eq(friendId))
                    .where(qFriendsConfirm.friendId.eq(userId))
                    .fetchFirst();
            if (StringUtils.hasText(confirmId)) {
                updateConfirm(confirmId, null, 1);
                continue;
            }

            // 开始发起加好友
            FriendsConfirm confirm = new FriendsConfirm();
            // confirm.getUserId是我的ID、confirm.getFriendId是好友的ID，我加别人
            confirm.setUserId(userId);
            confirm.setFriendId(friendId);
            confirm.setNotice(notice);

            User userMe = userFeignClient.getUser(confirm.getUserId()).getData();
            // 是否自动确认加好友
            if (friendInfo.getAutoAgreeAddMe().equals(1)) {
                confirm.setHandleFlag(1);

                Forumnotice forumnotice = new Forumnotice();
                forumnotice.setUserId(userId);
                forumnotice.setSourceId(friendId);
                forumnotice.setNoticeUserId(friendInfo.getUserId());
                forumnotice.setNoticeType("agreeToBeFriend");
                forumnotice.setNoticeUserNickname(friendInfo.getName());
                forumnotice.setNoticeUserHeadUrl(friendInfo.getImageUrl());
                forumnotice.setSourceDesc("确认添加你为好友");
                forumClient.saveNotice(forumnotice);

                User friend = userFeignClient.getUser(confirm.getFriendId()).getData();
                Forumnotice friendnotice = new Forumnotice();
                friendnotice.setUserId(friendId);
                friendnotice.setSourceId(confirm.getFriendId());
                friendnotice.setNoticeUserId(userId);
                friendnotice.setNoticeType("automaticToBeFriends");
                friendnotice.setNoticeUserNickname("你");
                friendnotice.setNoticeUserHeadUrl(userMe.getImageUrl());
                friendnotice.setSourceDesc("【自动确认】添加"+userMe.getName()+"为好友");
                forumClient.saveNotice(friendnotice);
                friendsService.saveFriends(userId, friendId);

            } else {
                confirm.setHandleFlag(0);
            }
            Forumnotice forumnotice = new Forumnotice();
            forumnotice.setUserId(confirm.getFriendId());
            forumnotice.setSourceId(confirm.getUserId());
            forumnotice.setNoticeType("addMeToBeFriend");
            forumnotice.setNoticeUserNickname(userMe.getName());
            forumnotice.setNoticeUserHeadUrl(userMe.getImageUrl());
            forumnotice.setSourceDesc("申请加你为好友");
            forumClient.saveNotice(forumnotice);

            //发送一条推送
            forumClient.pushMessageForExtraMsg(friendInfo.getNoticeRegId(),
                    FriendsConfirmService.TITLE, userMe.getName() + FriendsConfirmService.APPLYTOBEFRIENDMSG,
                    FriendsConfirmService.APPLYTOBEFRIEND);

            updateOrInsert(confirm);
        }
    }

    /**
     * 更新好友请求
     */
    public void updateConfirm(String confirmId, String notice, Integer handleFlag) {
        if (!StringUtils.hasText(confirmId)) {
            throw new AppException("好友请求ID不能为空");
        }
        if (handleFlag == null) {
            throw new AppException("请求处理方式不能为空");
        }
        FriendsConfirm confirm = getConfirmById(confirmId);
        // confirm.getUserId是好友的ID、confirm.getFriendId是我的ID，别人加我
        if (null == confirm) {
            throw new AppException("未找到申请记录");
        }
        confirm.setHandleFlag(handleFlag);
        confirm.setNotice(notice);

        if (handleFlag.equals(1)) {
            friendsService.saveFriends(confirm.getUserId(), confirm.getFriendId());
            User userMe = userFeignClient.getUser(confirm.getFriendId()).getData();
            User userFriend = userFeignClient.getUser(confirm.getUserId()).getData();
            Forumnotice forumnotice = new Forumnotice();
            forumnotice.setUserId(confirm.getUserId());
            forumnotice.setSourceId(confirm.getFriendId());
            forumnotice.setNoticeType("agreeToBeFriend");
            forumnotice.setNoticeUserNickname(userMe.getName());
            forumnotice.setNoticeUserHeadUrl(userMe.getImageUrl());
            forumnotice.setSourceDesc("确认添加你为好友");
            forumnotice.setNoticeUserId(userMe.getUserId());
            forumClient.saveNotice(forumnotice);

            //处理coolface同意添加好友请求
            if (StringUtils.hasText(confirm.getSearchId())) {
                //如果存在searchId，说明是人脸搜索的加好友请求
                //保存一条coolface通知,类型为确认加好友
                CoolfaceNotice coolfaceNotice = new CoolfaceNotice();
                FaceSearch faceSearch = faceSearchService.getFaceSearchBySearchId(confirm.getSearchId());
                if (null != faceSearch) {
                    //userId是当前用户的id， noticeUserId是通知当前用户的用户id
                    coolfaceNotice.setUserId(confirm.getUserId());
                    coolfaceNotice.setNoticeUserId(userMe.getUserId());
                    coolfaceNotice.setNoticeType(CoolfaceNoticeType.CONFIRMTOBEFRIEND);
                    coolfaceNotice.setHasRead(0);
                    coolfaceNotice.setNoticeId(GlobalIdWorker.nextString());
                    coolfaceNotice.setCreateDate(new Date());
                    coolfaceNotice.setBornDate(new Date(userMe.getBornDate().getTime()));
                    coolfaceNotice.setConfirmId(confirm.getConfirmId());
                    coolfaceNotice.setFacePicUrl(faceSearch.getFacePicUrl());
                    //已经是好友
                    coolfaceNotice.setFriendHandle(1);
                    coolfaceNotice.setJobName(userMe.getJobName());
                    coolfaceNotice.setMsg(faceSearch.getMsg());
                    coolfaceNotice.setNoticeUserGender(userMe.getGender());
                    coolfaceNotice.setNoticeUserName(userMe.getName());
                    coolfaceNotice.setNoticeUserImageUrl(userMe.getImageUrl());
                    coolfaceNotice.setSimilarRate(Double.valueOf(faceSearch.getSimilarity()));
                    coolfaceNotice.setNoticeUserProvince(userMe.getProvince());
                    coolfaceNotice.setNoticeUserCity(userMe.getCity());
                    userFeignClient.saveNotice(coolfaceNotice);
                    logger.info("coolface通知保存成功！");

                    //发送推送消息
                    forumClient.pushMessageForExtraMsg(userFriend.getNoticeRegId(),
                            FriendsConfirmService.TITLE, FriendsConfirmService.COOLFACECONFIRMTOBEFRIENDMSG,
                            FriendsConfirmService.COOLFACECONFIRMTOBEFRIEND);
                }
            }else{
                //推送消息
                forumClient.pushMessageForExtraMsg(userFriend.getNoticeRegId(),
                        FriendsConfirmService.TITLE, userMe.getName() + FriendsConfirmService.CONFIRMTOBEFRIENDMSG,
                        FriendsConfirmService.CONFIRMTOBEFRIEND+","+userMe.getUserId());
            }
        }
        queryFactory.update(qFriendsConfirm)
                .populate(confirm)
                .where(qFriendsConfirm.confirmId.eq(confirmId))
                .execute();
        // 同意或拒绝时双方的请求都一致
        queryFactory.update(qFriendsConfirm)
                .set(qFriendsConfirm.handleFlag, handleFlag)
                .where(qFriendsConfirm.userId.eq(confirm.getFriendId()))
                .where(qFriendsConfirm.friendId.eq(confirm.getUserId()))
                .execute();
    }

    /**
     * 自动更新好友请求
     */
    public long autoUpdate(String userId) {
        if (!StringUtils.hasText(userId)) {
            throw new AppException("用户ID不能为空");
        }

        // 查询所有添加我为好友的请求
        List<FriendsConfirm> confirmList = queryFactory.selectFrom(qFriendsConfirm)
                .where(qFriendsConfirm.friendId.eq(userId))
                .fetch();

        User userMe = userFeignClient.getUser(userId).getData();

        SQLUpdateClause update = queryFactory.update(qFriendsConfirm);
        for (FriendsConfirm confirm : confirmList) {
            // confirm.getUserId是好友的ID、confirm.getFriendId是我的ID，别人加我
            Forumnotice forumnotice = new Forumnotice();
            forumnotice.setUserId(confirm.getUserId());
            forumnotice.setSourceId(confirm.getFriendId());
            forumnotice.setNoticeType("agreeToBeFriend");
            forumnotice.setNoticeUserNickname(userMe.getName());
            forumnotice.setNoticeUserHeadUrl(userMe.getImageUrl());
            forumnotice.setSourceDesc("确认添加你为好友");
            forumClient.saveNotice(forumnotice);
            // 系统自动确认时通知自己
            User friend = userFeignClient.getUser(confirm.getUserId()).getData();
            Forumnotice friendnotice = new Forumnotice();
            friendnotice.setUserId(confirm.getFriendId());
            friendnotice.setSourceId(confirm.getUserId());
            friendnotice.setNoticeType("automaticToBeFriends");
            friendnotice.setNoticeUserNickname(friend.getName());
            friendnotice.setNoticeUserHeadUrl(friend.getImageUrl());
            friendnotice.setSourceDesc("【自动确认】添加为好友");
            forumClient.saveNotice(friendnotice);
            friendsService.saveFriends(confirm.getUserId(), confirm.getFriendId());
            update.set(qFriendsConfirm.handleFlag, 1)
                    .where(qFriendsConfirm.confirmId.eq(confirm.getConfirmId())
                            // 我加对方的好友请求也同意
                            .or(qFriendsConfirm.userId.eq(confirm.getFriendId())
                                    .and(qFriendsConfirm.friendId.eq(confirm.getUserId()))))
                    .addBatch();
        }
        return update.isEmpty() ? 0L : update.execute();
    }

    public long deleteConfirm(String userId, String friendId) {
        if (!StringUtils.hasText(userId)) {
            throw new AppException("用户ID不能为空");
        }
        if (!StringUtils.hasText(friendId)) {
            throw new AppException("好友ID不能为空");
        }
        return queryFactory.delete(qFriendsConfirm)
                .where(qFriendsConfirm.userId.eq(userId))
                .where(qFriendsConfirm.friendId.eq(friendId))
                .execute();
    }

    public List<FindFriendsConfirmVO> findFriendsConfirm(String userId, Integer handleFlag) {
        if (!StringUtils.hasText(userId)) {
            throw new AppException("用户ID不能为空");
        }
        //查询出请求加我为好友的记录，表中的userId为发起加好友的人，friendId为被加的人
        SQLQuery<FriendsConfirm> query = queryFactory.selectFrom(qFriendsConfirm)
                .where(qFriendsConfirm.friendId.eq(userId));
        if (handleFlag != null) {
            query.where(qFriendsConfirm.handleFlag.eq(handleFlag));
        }
        List<FriendsConfirm> confirms = query.fetch();

        List<FindFriendsConfirmVO> confirmVOS = new ArrayList<>();

        String[] friendIds = confirms.stream().map(FriendsConfirm::getUserId).toArray(String[]::new);
        DataCounts counts = friendsService.mutualFriendsCount(userId, friendIds);

        for (FriendsConfirm confirm : confirms) {
            FindFriendsConfirmVO findFriendsConfirmVO = new FindFriendsConfirmVO();
            findFriendsConfirmVO.setConfirmId(confirm.getConfirmId());
            findFriendsConfirmVO.setHandleFlag(confirm.getHandleFlag());
            // 查询用户信息
            User user = userFeignClient.getUser(confirm.getUserId()).getData();
            findFriendsConfirmVO.setUser(user);
            // 查询共同好友
            findFriendsConfirmVO.setMutualFriendCount(counts.getCount(user.getUserId()));
            confirmVOS.add(findFriendsConfirmVO);
        }
        return confirmVOS;
    }

    public List<String> findMyConfirm(String userId) {
        if (!StringUtils.hasText(userId)) {
            throw new AppException("用户ID不能为空");
        }
        return queryFactory.select(qFriendsConfirm.friendId)
                .from(qFriendsConfirm)
                .where(qFriendsConfirm.userId.eq(userId))
                .where(qFriendsConfirm.handleFlag.eq(0))
                .fetch();
    }

}
